package main

import (
	"github.com/gin-gonic/gin"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"net/http"
	"sync"

	"golang.org/x/time/rate"
)

const dsn = "gva:gvagva@tcp(172.1.4.155:3306)/gormtest?charset=utf8mb4&parseTime=True&loc=Local"

type UserTop struct {
	gorm.Model
	Name string `gorm:"unique"` // 添加 unique 标签
	Age  int8
	Hit  int64
	Ip   string
}

// NewIPRateLimiter 创建一个新的 IP 限流器
func NewIPRateLimiter(r rate.Limit, b int) *IPRateLimiter {
	i := &IPRateLimiter{
		ips: make(map[string]*rate.Limiter),
		mu:  &sync.RWMutex{},
		r:   r,
		b:   b,
	}
	return i
}

// IPRateLimiter 用于存储每个 IP 的限流器
type IPRateLimiter struct {
	ips map[string]*rate.Limiter
	mu  *sync.RWMutex
	r   rate.Limit
	b   int
}

// GetLimiter 获取指定 IP 的限流器，如果不存在则创建一个
func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter {
	i.mu.Lock()
	defer i.mu.Unlock()

	limiter, exists := i.ips[ip]
	if !exists {
		limiter = rate.NewLimiter(i.r, i.b)
		i.ips[ip] = limiter
	}

	return limiter
}

// IPRateLimitMiddleware 限流中间件
func IPRateLimitMiddleware(limiter *IPRateLimiter) gin.HandlerFunc {
	return func(c *gin.Context) {
		clientIP := c.ClientIP()
		if !limiter.GetLimiter(clientIP).Allow() {
			c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{
				"error": "请求过于频繁，请稍后再试",
			})
			return
		}
		c.Next()
	}
}

func main() {
	rateLimiter := NewIPRateLimiter(1, 1)
	// 连接数据库
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("连接数据库失败")
	}
	db.AutoMigrate(&UserTop{})

	//添加记录
	db.Create(&UserTop{Name: "admin", Hit: 1})

	router := gin.Default()
	router.Use(IPRateLimitMiddleware(rateLimiter))
	router.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	router.GET("/view", func(c *gin.Context) {
		var users []UserTop
		// 按照 Hit 字段降序排序，取前 15 条记录
		db.Order("Hit DESC").Select("id", "name", "hit").Limit(50).Find(&users)
		c.JSON(200, gin.H{
			"message": "view  some things  ", //翻译
			"msg":     "显示一些信息 我的博客我做主 ",
			"users":   users,
		})
	})

	router.GET("/data", func(c *gin.Context) {
		var users []UserTop
		// 按照 Hit 字段降序排序，取前 15 条记录
		db.Order("Hit DESC").Select("id", "name", "hit").Limit(50).Find(&users)
		c.JSON(200, gin.H{
			"message": "view  some things  ", //翻译
			"msg":     "显示一些信息 我的博客我做主 ",
			"users":   users,
		})
	})

	router.LoadHTMLGlob("templates/*")
	router.GET("/index", func(c *gin.Context) {
		var users []UserTop
		var count int64 = 0
		db.Model(&UserTop{}).Count(&count)
		// 按照 Hit 字段降序排序，取前 15 条记录
		db.Order("Hit ASC").Select("id", "name", "hit").Where("id <?", 10000).Limit(50).Find(&users)
		c.HTML(http.StatusOK, "index.tmpl", gin.H{
			"title": " 个人点击率排行榜   ",
			"msg":   " 我的博客我做主   ",
			"users": users,
			"count": count,
		})
	})
	router.Run(":8888") // 监听并在 0.0.0.0:8080 上启动服务
}
